home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / os2 / memsz313.zip / SOURCE.ZIP / SNAPSHOT.CPP < prev    next >
Text File  |  1996-03-19  |  22KB  |  636 lines

  1. /*************************************************************** SNAPSHOT.CPP
  2.  *                                                                          *
  3.  *           Standalone Text-mode Snapshot of System Resources              *
  4.  *                                                                          *
  5.  ****************************************************************************/
  6.  
  7. #define INCL_BASE
  8. #define INCL_PM
  9. #include <os2.h>
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include "Config.h"
  16. #include "DQPS.h"
  17. #include "MemSize.h"
  18. #include "Module.h"
  19. #include "ReString.h"
  20. #include "Support.h"
  21.  
  22.  
  23. /****************************************************************************
  24.  *                                                                          *
  25.  *                       Definitions & Declarations                         *
  26.  *                                                                          *
  27.  ****************************************************************************/
  28.  
  29. static void FormatValue ( long Value, char Text[], COUNTRYINFO &CountryInfo, int ShowK=SHOWK_ABOVE512, int Scale=1 ) ;
  30. static PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) ;
  31. static char *CopyString ( char *Buffer, char *Original ) ;
  32. static int CheckDrive ( USHORT Drive, PBYTE FileSystem, PBYTE DiskLabel ) ;
  33.  
  34.  
  35. /****************************************************************************
  36.  *                                                                          *
  37.  *                              Mainline                                    *
  38.  *                                                                          *
  39.  ****************************************************************************/
  40.  
  41. extern int main ( int argc, char *argv[] ) {
  42.  
  43.    // Initialization
  44.  
  45.    Module Library ( PSZ(PROGRAM_NAME) ) ;
  46.  
  47.    COUNTRYCODE CountryCode ;
  48.    CountryCode.country = 0 ;
  49.    CountryCode.codepage = 0 ;
  50.  
  51.    COUNTRYINFO CountryInfo ;
  52.    ULONG Count ;
  53.    ULONG Status = DosGetCtryInfo ( sizeof(CountryInfo), &CountryCode, &CountryInfo, &Count ) ;
  54.    if ( Status ) {
  55.       CountryInfo.fsDateFmt = DATEFMT_MM_DD_YY ;
  56.       CountryInfo.fsTimeFmt = 0 ;
  57.       CountryInfo.szDateSeparator[0] = '/' ;
  58.       CountryInfo.szDateSeparator[1] = 0 ;
  59.       CountryInfo.szTimeSeparator[0] = ':' ;
  60.       CountryInfo.szTimeSeparator[1] = 0 ;
  61.       CountryInfo.szThousandsSeparator[0] = ',' ;
  62.       CountryInfo.szThousandsSeparator[1] = 0 ;
  63.    } /* endif */
  64.  
  65.    char Text [80] ;
  66.    ULONG Size = 2 ;
  67.    if ( PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("iDate"), Text, &Size ) ) {
  68.       CountryInfo.fsDateFmt = atoi ( Text ) ;
  69.    } /* endif */
  70.  
  71.    Size = 2 ;
  72.    if ( PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("iTime"), Text, &Size ) ) {
  73.       CountryInfo.fsTimeFmt = UCHAR ( atoi ( Text ) ) ;
  74.    } /* endif */
  75.  
  76.    Size = 2 ;
  77.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("sDate"), CountryInfo.szDateSeparator, &Size ) ;
  78.  
  79.    Size = 2 ;
  80.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("sTime"), CountryInfo.szTimeSeparator, &Size ) ;
  81.  
  82.    Size = 3 ;
  83.    char szAm [3] ;
  84.    strcpy ( szAm, "am" ) ;
  85.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("s1159"), szAm, &Size ) ;
  86.  
  87.    Size = 3 ;
  88.    char szPm [3] ;
  89.    strcpy ( szPm, "pm" ) ;
  90.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("s2359"), szPm, &Size ) ;
  91.  
  92.    Size = 2 ;
  93.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("sThousand"), CountryInfo.szThousandsSeparator, &Size ) ;
  94.  
  95.    PSZ Swappath = ScanSystemConfig ( 0, PSZ("SWAPPATH") ) ;
  96.    if ( Swappath == NULL ) 
  97.       Swappath = PSZ("C:\\OS2\\SYSTEM 0") ;
  98.    char SwapPath [CCHMAXPATH] ;
  99.    char *p = CopyString ( SwapPath, PCHAR(Swappath) ) ;
  100.    ULONG MinFree ;
  101.    sscanf ( p, " %li", &MinFree ) ;
  102.    printf ( "SwapPath '%s', MinFree %iK.\n", SwapPath, MinFree ) ;
  103.  
  104.    PSZ SpoolPath = 0 ;
  105.    if ( PrfQueryProfileSize ( HINI_PROFILE, PSZ("PM_SPOOLER"), PSZ("DIR"), &Size ) ) {
  106.       SpoolPath = PSZ ( malloc ( (int)Size ) ) ;
  107.       if ( SpoolPath ) {
  108.          if ( PrfQueryProfileData ( HINI_PROFILE, PSZ("PM_SPOOLER"), PSZ("DIR"), SpoolPath, &Size ) ) {
  109.             PBYTE p = PBYTE( strchr ( PCHAR(SpoolPath), ';' ) ) ;
  110.             if ( p ) {
  111.                *p = 0 ;
  112.             } /* endif */
  113.          } else {
  114.             free ( SpoolPath ) ;
  115.             SpoolPath = 0 ;
  116.          } /* endif */
  117.       } /* endif */
  118.    } /* endif */
  119.    if ( SpoolPath == 0 )
  120.       SpoolPath = PSZ ( "C:\\SPOOL" ) ;
  121.  
  122.  
  123.    // Date and Time
  124.  
  125.    DATETIME DateTime ;
  126.    DosGetDateTime ( &DateTime ) ;
  127.  
  128.    ResourceString DaysOfWeek ( Library.QueryHandle(), IDS_DAYSOFWEEK ) ;
  129.  
  130.    switch ( CountryInfo.fsDateFmt ) {
  131.       case DATEFMT_DD_MM_YY:
  132.          sprintf ( Text, "%0.*s, %02lu%s%02lu ",
  133.             strlen(PCHAR(DaysOfWeek))/7, PSZ(DaysOfWeek) + DateTime.weekday*(strlen(PCHAR(DaysOfWeek))/7),
  134.             DateTime.day, CountryInfo.szDateSeparator, DateTime.month ) ;
  135.          break ;
  136.       case DATEFMT_YY_MM_DD:
  137.          sprintf ( Text, "%02lu%s%02lu %0.*s ",
  138.             DateTime.month, CountryInfo.szDateSeparator, DateTime.day,
  139.             strlen(PCHAR(DaysOfWeek))/7, PSZ(DaysOfWeek) + DateTime.weekday*(strlen(PCHAR(DaysOfWeek))/7) ) ;
  140.          break ;
  141.       case DATEFMT_MM_DD_YY:
  142.       default:
  143.          sprintf ( Text, "%0.*s, %02lu%s%02lu ",
  144.             strlen(PCHAR(DaysOfWeek))/7, PSZ(DaysOfWeek) + DateTime.weekday*(strlen(PCHAR(DaysOfWeek))/7),
  145.             DateTime.month, CountryInfo.szDateSeparator, DateTime.day ) ;
  146.          break ;
  147.    } /* endswitch */
  148.  
  149.    if ( CountryInfo.fsTimeFmt ) {
  150.       sprintf ( Text+strlen(Text), "%02lu%s%02lu", DateTime.hours, CountryInfo.szTimeSeparator, DateTime.minutes ) ;
  151.    } else {
  152.       PCHAR AmPm ;
  153.       if ( DateTime.hours ) {
  154.          if ( DateTime.hours < 12 ) {
  155.             AmPm = szAm ;
  156.          } else if ( DateTime.hours == 12 ) {
  157.             if ( DateTime.minutes )
  158.                AmPm = szPm ;
  159.             else
  160.                AmPm = szAm ;
  161.          } else if ( DateTime.hours > 12 ) {
  162.             DateTime.hours -= 12 ;
  163.             AmPm = szPm ;
  164.          } /* endif */
  165.       } else {
  166.          DateTime.hours = 12 ;
  167.          if ( DateTime.minutes )
  168.             AmPm = szAm ;
  169.          else
  170.             AmPm = szPm ;
  171.       } /* endif */
  172.       sprintf ( Text+strlen(Text), "%02lu%s%02lu%s", DateTime.hours, CountryInfo.szTimeSeparator, DateTime.minutes, AmPm ) ;
  173.    } /* endif */
  174.    printf ( "%*s%s", 40-strlen(Text)/2, "", Text ) ;
  175.    printf ( "\n" ) ;
  176.  
  177.  
  178.    // Elapsed Time
  179.  
  180.    ResourceString ElapsedLabel ( Library.QueryHandle(), IDS_ELAPSED ) ;
  181.    int Column = printf ( "%s", PSZ(ElapsedLabel) ) ;
  182.    strcpy ( Text, "" ) ;
  183.  
  184.    ULONG Milliseconds ;
  185.    DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &Milliseconds, sizeof(Milliseconds) ) ;
  186.  
  187.    ULONG Time = Milliseconds / 60000L ;
  188.  
  189.    ULONG NumberOfDays = Time / ( 60L * 24L ) ;
  190.  
  191.    if ( NumberOfDays ) {
  192.       ResourceString Day ( Library.QueryHandle(), IDS_DAY ) ;
  193.       ResourceString Days ( Library.QueryHandle(), IDS_DAYS ) ;
  194.       sprintf ( Text+strlen(Text), "%lu %s, ", NumberOfDays, NumberOfDays > 1 ? PSZ(Days) : PSZ(Day) ) ;
  195.    } /* endif */
  196.  
  197.    ULONG Minutes = Time % ( 60L * 24L ) ;
  198.    sprintf ( Text+strlen(Text), "%lu%s%02lu ", Minutes/60, CountryInfo.szTimeSeparator, Minutes%60 ) ;
  199.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  200.    printf ( "\n" ) ;
  201.  
  202.  
  203.    // Physical Memory Free
  204.  
  205.    ResourceString PhysicalMemoryFree ( Library.QueryHandle(), IDS_MEMORY ) ;
  206.    Column = printf ( "%s", PSZ(PhysicalMemoryFree) ) ;
  207.    APIRET16 APIENTRY16 Dos16MemAvail ( PULONG pulAvailMem ) ;
  208.    ULONG PhysMemFree ;
  209.    Dos16MemAvail ( &PhysMemFree ) ;
  210.    FormatValue ( PhysMemFree, Text, CountryInfo ) ;
  211.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  212.    printf ( "\n" ) ;
  213.  
  214.  
  215.    // Virtual Memory Free
  216.  
  217.    ResourceString VirtualMemoryFree ( Library.QueryHandle(), IDS_VIRTUAL ) ;
  218.    Column = printf ( "%s", PSZ(VirtualMemoryFree) ) ;
  219.    ULONG VirtMemFree ;
  220.    DosQuerySysInfo ( QSV_TOTAVAILMEM, QSV_TOTAVAILMEM, &VirtMemFree, sizeof(VirtMemFree) ) ;
  221.    FormatValue ( VirtMemFree, Text, CountryInfo ) ;
  222.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  223.    printf ( "\n" ) ;
  224.  
  225.  
  226.    // Swapfile Size
  227.  
  228.    ResourceString SwapfileSize ( Library.QueryHandle(), IDS_SWAPSIZE ) ;
  229.    Column = printf ( "%s", PSZ(SwapfileSize) ) ;
  230.    ULONG PathSize ;
  231.    DosQuerySysInfo ( QSV_MAX_PATH_LENGTH, QSV_MAX_PATH_LENGTH, &PathSize, sizeof(PathSize) ) ;
  232.    PBYTE Path = PBYTE ( malloc ( size_t(PathSize) ) ) ;
  233.    strcpy ( PCHAR(Path), PCHAR(SwapPath) ) ;
  234.    if ( Path[strlen(PCHAR(Path))-1] != '\\' ) {
  235.       strcat ( PCHAR(Path), "\\" ) ;
  236.    } /* endif */
  237.    strcat ( PCHAR(Path), "SWAPPER.DAT" ) ;
  238.    ULONG SwapSize = 0 ;
  239.    FILESTATUS3 FileStatus ;
  240.    if ( DosQueryPathInfo ( (PSZ)Path, FIL_STANDARD, &FileStatus, sizeof(FileStatus) ) == 0 ) {
  241.       SwapSize = FileStatus.cbFileAlloc ;
  242.    } /* endif */
  243.    free ( Path ) ;
  244.    FormatValue ( SwapSize, Text, CountryInfo ) ;
  245.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  246.    printf ( "\n" ) ;
  247.  
  248.  
  249.    // Available Swap Space
  250.  
  251.    ResourceString SwapspaceFree ( Library.QueryHandle(), IDS_SWAPFREE ) ;
  252.    Column = printf ( "%s", PSZ(SwapspaceFree) ) ;
  253.    Path = PBYTE ( malloc ( size_t(PathSize) ) ) ;
  254.    strcpy ( PCHAR(Path), (PCHAR)SwapPath ) ;
  255.    strcat ( PCHAR(Path), "\\SWAPPER.DAT" ) ;
  256.    ULONG SwapFree = 0 ;
  257.    if ( Path[0] ) {
  258.       DosError ( FERR_DISABLEHARDERR ) ;
  259.       FSALLOCATE Allocation ;
  260.       DosQueryFSInfo ( Path[0]-'A'+1, FSIL_ALLOC, (PBYTE)&Allocation, sizeof(Allocation) ) ;
  261.       DosError ( FERR_ENABLEHARDERR ) ;
  262.       SwapFree = Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ;
  263.    } /* endif */
  264.    if ( SwapFree < ULONG(MinFree*1024L) )
  265.       SwapFree = 0 ;
  266.    else
  267.       SwapFree = SwapFree - ULONG(MinFree*1024L) ;
  268.    free ( Path ) ;
  269.    FormatValue ( SwapFree, Text, CountryInfo ) ;
  270.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  271.    printf ( "\n" ) ;
  272.  
  273.  
  274.    // Swapfile Slack Space
  275.  
  276.    ResourceString SwapslackFree ( Library.QueryHandle(), IDS_SWAPSLACK ) ;
  277.    Column = printf ( "%s", PSZ(SwapslackFree) ) ;
  278.    LONG SwapSlack = VirtMemFree - SwapFree - PhysMemFree ;
  279.    SwapSlack = max ( 0, SwapSlack ) ;
  280.    FormatValue ( SwapSlack, Text, CountryInfo ) ;
  281.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  282.    printf ( "\n" ) ;
  283.  
  284.  
  285.    // Spoolfile Size
  286.  
  287.    ResourceString SpoolSize ( Library.QueryHandle(), IDS_SPOOLSIZE ) ;
  288.    Column = printf ( "%s", PSZ(SpoolSize) ) ;
  289.    Path = PBYTE ( malloc ( size_t(PathSize) ) ) ;
  290.    PFILEFINDBUF3 Found = PFILEFINDBUF3 ( malloc ( size_t(PathSize+sizeof(FILEFINDBUF3)) ) ) ;
  291.    strcpy ( (PCHAR)Path, (PCHAR)SpoolPath ) ;
  292.    strcat ( (PCHAR)Path, "\\*.*" ) ;
  293.    HDIR hDir = (HDIR) HDIR_CREATE ;
  294.    Count = 1 ;
  295.    ULONG TotalSize = 0 ;
  296.    if ( !DosFindFirst2 ( Path, &hDir,
  297.       FILE_NORMAL | FILE_READONLY | FILE_DIRECTORY | FILE_ARCHIVED,
  298.       Found, PathSize+sizeof(FILEFINDBUF3), &Count, FIL_STANDARD ) ) {
  299.       do {
  300.          if ( !strcmp ( (PCHAR)Found->achName, "." ) OR !strcmp ( (PCHAR)Found->achName, ".." ) ) {
  301.             continue ;
  302.          } /* endif */
  303.          if ( Found->attrFile & FILE_DIRECTORY ) {
  304.             HDIR hDir2 = (HDIR) HDIR_CREATE ;
  305.             strcpy ( (PCHAR)Path, (PCHAR)SpoolPath ) ;
  306.             strcat ( (PCHAR)Path, "\\" ) ;
  307.             strcat ( (PCHAR)Path, (PCHAR)Found->achName ) ;
  308.             strcat ( (PCHAR)Path, "\\*.*" ) ;
  309.             ULONG Count2 = 1 ;
  310.             if ( !DosFindFirst2 ( Path, &hDir2,
  311.                FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED,
  312.                Found, PathSize+sizeof(FILEFINDBUF3), &Count2, FIL_STANDARD ) ) {
  313.                do {
  314.                   TotalSize += Found->cbFileAlloc ;
  315.                } while ( !DosFindNext ( hDir2, Found, PathSize+sizeof(FILEFINDBUF3), &Count2 ) ) ;
  316.                DosFindClose ( hDir2 ) ;
  317.             } /* endif */
  318.          } else {
  319.             TotalSize += Found->cbFileAlloc ;
  320.          } /* endif */
  321.       } while ( !DosFindNext ( hDir, Found, PathSize+sizeof(FILEFINDBUF3), &Count ) ) ;
  322.       DosFindClose ( hDir ) ;
  323.    } /* endif */
  324.    free ( Path ) ;
  325.    free ( Found ) ;
  326.    FormatValue ( TotalSize, Text, CountryInfo ) ;
  327.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  328.    printf ( "\n" ) ;
  329.  
  330.  
  331.    // Active Task Count
  332.  
  333.    ResourceString ActiveTaskCount ( Library.QueryHandle(), IDS_TASKCOUNT ) ;
  334.    Column = printf ( "%s", PSZ(ActiveTaskCount) ) ;
  335.    ULONG TaskCount = WinQuerySwitchList ( 0, 0, 0 ) ;
  336.    sprintf ( Text, "%i ", TaskCount ) ;
  337.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  338.    printf ( "\n" ) ;
  339.  
  340.  
  341.    // Process Count
  342.  
  343.    ResourceString ProcessCount ( Library.QueryHandle(), IDS_PROCESSCOUNT ) ;
  344.    Column = printf ( "%s", PSZ(ProcessCount) ) ;
  345.    int ProcCount = 0 ;
  346.    PULONG DQPS_Buffer ;
  347.    DosAllocMem ( (PPVOID)&DQPS_Buffer, 0x10000, PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE ) ;
  348.    if ( !DosQProcStatus ( DQPS_Buffer, 0xFFFF ) ) {
  349.       qsPrec_s *pProcRecord = ((qsPtrRec_s*)DQPS_Buffer)->pProcRec ;
  350.       while ( pProcRecord->RecType == 1 ) {
  351.          int Size = sizeof(qsPrec_s) ;
  352.          Size += pProcRecord->cTCB * sizeof(qsTrec_s) ;
  353.          Size += pProcRecord->c16Sem * sizeof(short) ;
  354.          Size += pProcRecord->cLib * sizeof(short) ;
  355.          Size += pProcRecord->cShrMem * sizeof(short) ;
  356.          pProcRecord = (qsPrec_s*) ( (char*)pProcRecord + Size ) ;
  357.          ProcCount ++ ;
  358.       } /* endwhile */
  359.    } /* endif */
  360.    DosFreeMem ( DQPS_Buffer ) ;
  361.    sprintf ( Text, "%i ", ProcCount ) ;
  362.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  363.    printf ( "\n" ) ;
  364.  
  365.  
  366.    // Thread Count
  367.  
  368.    ResourceString ThreadCount ( Library.QueryHandle(), IDS_THREADCOUNT ) ;
  369.    Column = printf ( "%s", PSZ(ThreadCount) ) ;
  370.    int ThrdCount = 0 ;
  371.    DosAllocMem ( (PPVOID)&DQPS_Buffer, 0x10000, PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE ) ;
  372.    if ( !DosQProcStatus ( DQPS_Buffer, 0xFFFF ) ) {
  373.       ThrdCount = int ( ((qsPtrRec_s*)DQPS_Buffer)->pGlobalRec->cThrds ) ;
  374.    } /* endif */
  375.    DosFreeMem ( DQPS_Buffer ) ;
  376.    sprintf ( Text, "%i ", ThrdCount ) ;
  377.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  378.    printf ( "\n" ) ;
  379.  
  380.  
  381.    // Total Free Space
  382.  
  383.    ResourceString TotalFree ( Library.QueryHandle(), IDS_TOTALFREE ) ;
  384.    Column = printf ( "%s", PSZ(TotalFree) ) ;
  385.    ULONG Drive, Drives ;
  386.    DosQueryCurrentDisk ( &Drive, &Drives ) ;
  387.    ULONG Free = 0 ;
  388.    ULONG Mask = Drives >> 2 ;
  389.    for ( Drive=3; Drive<=26; Drive++ ) {
  390.       if ( Mask & 1 ) {
  391.          BYTE FileSystem [80] = { 0 } ;
  392.          BYTE DiskLabel [12] = { 0 } ;
  393.          if ( CheckDrive ( USHORT(Drive), FileSystem, DiskLabel ) ) {
  394.             DosError ( FERR_DISABLEHARDERR ) ;
  395.             FSALLOCATE Allocation ;
  396.             APIRET Status = DosQueryFSInfo ( Drive, FSIL_ALLOC, (PBYTE)&Allocation, sizeof(Allocation) ) ;
  397.             DosError ( FERR_ENABLEHARDERR ) ;
  398.             if ( Status ) {
  399.                Drives &= ~ ( 1 << (Drive-1) ) ;
  400.             } else {
  401.                Free += Allocation.cUnitAvail*Allocation.cSectorUnit*(Allocation.cbSector/256) ;
  402.             } /* endif */
  403.          } else {
  404.             Drives &= ~ ( 1 << (Drive-1) ) ;
  405.          } /* endif */
  406.       } /* endif */
  407.       Mask >>= 1 ;
  408.    } /* endfor */
  409.    FormatValue ( Free, Text, CountryInfo, SHOWK_ABOVE512, 256 ) ;
  410.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  411.    printf ( "\n" ) ;
  412.  
  413.  
  414.    // Drive Space Free
  415.    ResourceString DriveFree ( Library.QueryHandle(), IDS_DRIVE_FREE ) ;
  416.    Mask = Drives >> 2 ;
  417.    for ( Drive=3; Drive<=26; Drive++ ) {
  418.       if ( Mask & 1 ) {
  419.          BYTE FileSystem [80] = { 0 } ;
  420.          BYTE DiskLabel [12] = { 0 } ;
  421.          if ( CheckDrive ( USHORT(Drive), FileSystem, DiskLabel ) ) {
  422.             DosError ( FERR_DISABLEHARDERR ) ;
  423.             FSALLOCATE Allocation ;
  424.             APIRET Status = DosQueryFSInfo ( Drive, FSIL_ALLOC, (PBYTE)&Allocation, sizeof(Allocation) ) ;
  425.             DosError ( FERR_ENABLEHARDERR ) ;
  426.             if ( Status ) {
  427.                Drives &= ~ ( 1 << (Drive-1) ) ;
  428.             } else {
  429.                char Label [80] ;
  430.                sprintf ( Label, PCHAR(DriveFree), Drive+'A'-1 ) ;
  431.                Column = printf ( "%s (%s,%s)", Label, DiskLabel, FileSystem ) ;
  432.                Free = Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ;
  433.                FormatValue ( Free, Text, CountryInfo ) ;
  434.                printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  435.                printf ( "\n" ) ;
  436.             } /* endif */
  437.          } else {
  438.             Drives &= ~ ( 1 << (Drive-1) ) ;
  439.          } /* endif */
  440.       } /* endif */
  441.       Mask >>= 1 ;
  442.    } /* endfor */
  443.  
  444.    return ( 0 ) ;
  445. }
  446.  
  447. static void FormatValue ( long Value, char Text[], COUNTRYINFO &CountryInfo, int ShowK, int Scale ) {
  448.  
  449.    switch ( ShowK ) {
  450.       case SHOWK_NEVER:
  451.          sprintf ( Text, "%lu", Value*Scale ) ;
  452.          break;
  453.       case SHOWK_ALWAYS:
  454.          sprintf ( Text, "%lu", (Value+(512/Scale))/(1024/Scale) ) ;
  455.          break;
  456.       case SHOWK_ABOVE512:
  457.       default:
  458.          if ( Value < 0x80000/Scale )
  459.             sprintf ( Text, "%lu", Value*Scale ) ;
  460.          else
  461.             sprintf ( Text, "%lu", (Value+(512/Scale))/(1024/Scale) ) ;
  462.          break;
  463.    } /* endswitch */
  464.  
  465.    char Work[100] ;
  466.    char *p1 = Text ;
  467.    char *p2 = Work ;
  468.    while ( *p1 ) {
  469.       *p2 = *p1 ;
  470.       p1 ++ ;
  471.       p2 ++ ;
  472.       if ( *p1 ) {
  473.          if ( strlen(p1) % 3 == 0 ) {
  474.             *p2 = CountryInfo.szThousandsSeparator [0] ;
  475.             p2 ++ ;
  476.          } /* endif */
  477.       } /* endif */
  478.    } /* endwhile */
  479.    *p2 = 0 ;
  480.    strcpy ( Text, Work ) ;
  481.  
  482.    p2 = Text + strlen(Text) ;
  483.    *(p2+1) = 0 ;
  484.    switch ( ShowK ) {
  485.       case SHOWK_NEVER:
  486.          *p2 = ' ' ;
  487.          break;
  488.       case SHOWK_ALWAYS:
  489.          *p2 = 'K' ;
  490.          break;
  491.       case SHOWK_ABOVE512:
  492.       default:
  493.          if ( Value < 0x80000/Scale )
  494.             *p2 = ' ' ;
  495.          else
  496.             *p2 = 'K' ;
  497.          break;
  498.    } /* endswitch */
  499. }
  500.  
  501. static PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) {
  502.  
  503.    ULONG BootDrive ;
  504.    DosQuerySysInfo ( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &BootDrive, sizeof(BootDrive) ) ;
  505.  
  506.    WinUpper ( Anchor, 0, 0, Keyword ) ;
  507.  
  508.    char Path [_MAX_PATH] ;
  509.    Path[0] = (char) ( BootDrive + 'A' - 1 ) ;
  510.    Path[1] = 0 ;
  511.    strcat ( Path, ":\\CONFIG.SYS" ) ;
  512.  
  513.    FILE *File = fopen ( Path, "r" ) ;
  514.    if ( NOT File ) {
  515.       return ( 0 ) ;
  516.    } /* endif */
  517.  
  518.    static char Buffer [500] ;
  519.    while ( fgets ( Buffer, sizeof(Buffer), File ) ) {
  520.  
  521.       if ( Buffer[strlen(Buffer)-1] == '\n' ) 
  522.          Buffer[strlen(Buffer)-1] = 0 ;
  523.  
  524.       WinUpper ( Anchor, 0, 0, PSZ(Buffer) ) ;
  525.  
  526.       char *p = Buffer ;
  527.       while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
  528.  
  529.       if ( strncmp ( p, PCHAR(Keyword), strlen(PCHAR(Keyword)) ) )
  530.          continue ;
  531.  
  532.       p += strlen(PCHAR(Keyword)) ;
  533.       while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
  534.  
  535.       if ( *p++ != '=' )
  536.          continue ;
  537.  
  538.       while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
  539.  
  540.       fclose ( File ) ;
  541.       return ( PSZ(p) ) ;
  542.  
  543.    } /* endwhile */
  544.  
  545.    fclose ( File ) ;
  546.  
  547.    return ( 0 ) ;
  548. }
  549.  
  550. static char *CopyString ( char *Buffer, char *Original ) {
  551.    char *p1 = PCHAR(Original), *p2 = Buffer ;
  552.    BOOL Quoted = FALSE ;
  553.    *p2 = 0 ;
  554.    while ( *p1 ) {
  555.       if ( Quoted ) {
  556.          if ( *p1 == '"' ) {
  557.             Quoted = FALSE ;
  558.          } else {
  559.             *p2++ = *p1 ;
  560.             *p2 = 0 ;
  561.          } /* endif */
  562.       } else {
  563.          if ( *p1 == '"' ) {
  564.             Quoted = TRUE ;
  565.          } else if ( ( *p1 == ' ' ) OR ( *p1 == '\t' ) ) {
  566.             break ;
  567.          } else {
  568.             *p2++ = *p1 ;
  569.             *p2 = 0 ;
  570.          } /* endif */
  571.       } /* endif */
  572.       p1 ++ ;
  573.    } /* endwhile */ 
  574.    return ( p1 ) ;
  575. }
  576.  
  577. static int CheckDrive ( USHORT Drive, PBYTE FileSystem, PBYTE DiskLabel ) {
  578.  
  579.    BYTE Path [3] ;
  580.    Path[0] = (BYTE) ( Drive + 'A' - 1 ) ;
  581.    Path[1] = ':' ;
  582.    Path[2] = 0 ;
  583.  
  584.    DosError ( FERR_DISABLEHARDERR ) ;
  585.  
  586.    BYTE Buffer [1024] ;
  587.    ULONG Size = sizeof(Buffer) ;
  588.    ULONG Status = DosQueryFSAttach ( Path, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)Buffer, &Size ) ;
  589.    DosError ( FERR_ENABLEHARDERR ) ;
  590.  
  591.    if ( Status ) {
  592.       return ( 0 ) ;   // Don't monitor.
  593.    } /* endif */
  594.  
  595.    USHORT cbName = PFSQBUFFER2(Buffer)->cbName ;
  596.    strcpy ( PCHAR(FileSystem), PCHAR(PFSQBUFFER2(Buffer+cbName)->szFSDName) ) ;
  597.  
  598.    if ( PFSQBUFFER2(Buffer)->iType == FSAT_REMOTEDRV ) {
  599.       return ( -1 ) ;  // Monitor but don't include in the total over all drives.
  600.    } /* endif */
  601.  
  602.    ULONG Action ;
  603.    HFILE Handle ;
  604.    Status = DosOpen ( Path, &Handle, &Action, 0, 0, FILE_OPEN,
  605.       OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
  606.       OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) ;
  607.  
  608.    if ( Status ) {
  609.       return ( 0 ) ;   // Don't monitor.
  610.    } /* endif */
  611.  
  612.    BOOL Addit = FALSE ;
  613.    BYTE Command = 0 ;
  614.    BYTE NonRemovable ;
  615.  
  616.    ULONG LengthIn = sizeof(Command) ;
  617.    ULONG LengthOut = sizeof(NonRemovable);
  618.  
  619.    if ( NOT DosDevIOCtl ( Handle, 8, 0x20,
  620.       &Command, sizeof(Command), &LengthIn,
  621.       &NonRemovable, sizeof(NonRemovable), &LengthOut ) ) {
  622.  
  623.       Addit = NonRemovable ;
  624.  
  625.    } /* endif */
  626.  
  627.    DosClose ( Handle ) ;
  628.  
  629.    FSINFO Info ;
  630.    if ( DosQueryFSInfo ( Drive, FSIL_VOLSER, PBYTE(&Info), sizeof(Info) ) == 0 )
  631.       strcpy ( PCHAR(DiskLabel), PCHAR(Info.vol.szVolLabel) ) ;
  632.  
  633.    return ( int(Addit) ) ;    // Monitor and include in overall total if not removable.
  634. }
  635.  
  636.